import tensorflow as tf

# # -------------------二元梯度案例---------------------------
print("二元梯度")
x = tf.constant(value=3.0)
y = tf.constant(value=2.0)
with tf.GradientTape(persistent=True,watch_accessed_variables=True) as tape:
    tape.watch([x, y])  # 将w加入梯度跟踪列表
    z1 = x*x*y+x*y      # 构建计算过程
# 一阶导数
dz1_dx = tape.gradient(target=z1,sources=x)
dz1_dy = tape.gradient(target=z1, sources=y)
dz1_d = tape.gradient(target=z1,sources=[x, y])
print("dz1_dx:", dz1_dx)
print("dz1_dy:", dz1_dy)
print("dz1_d:", dz1_d)
print("type of dz1_d:", type(dz1_d))

'''
# # __init__(persistent=False,watch_accessed_variables=True)
# # 作用：创建一个新的GradientTape
# # 参数:
# # persistent: 布尔值，用来指定新创建的gradient tape是否是可持续性的。默认是False，意味着只能够调用一次gradient（）函数。
# # watch_accessed_variables: 布尔值，表明这个gradien tap是不是会自动追踪任何能被训练（trainable）的变量。默认是True。要是为False的话，意味着你需要手动去指定你想追踪的那些变量。
'''
# # watch(tensor)
# # 作用：确保某个tensor被tape追踪
# # 参数:
# # tensor: 一个Tensor或者一个Tensor列表
'''
# # gradient(target,sources,output_gradients=None,unconnected_gradients=tf.UnconnectedGradients.NONE)
# # 作用：根据tape上面的上下文来计算某个或者某些tensor的梯度
# # 参数:
target: 被微分的Tensor或者Tensor列表，你可以理解为经过某个函数之后的值
sources: Tensors 或者Variables列表（当然可以只有一个值）. 你可以理解为函数的某个变量
output_gradients: a list of gradients, one for each element of target. Defaults to None.
unconnected_gradients: a value which can either hold ‘none’ or ‘zero’ and alters the value which will be returned if the target and sources are unconnected. The possible values and effects are detailed in ‘UnconnectedGradients’ and it defaults to ‘none’.

返回:
一个列表表示各个变量的梯度值，和source中的变量列表一一对应，表明这个变量的梯度。
'''





''' # # Simple
# 创建4个张量
a = tf.constant(1.)
b = tf.constant(2.)
c = tf.constant(3.)
w = tf.constant(4.)


with tf.GradientTape() as tape:# 构建梯度环境
	tape.watch([w]) # 将w加入梯度跟踪列表
	# 构建计算过程
	y = a * w**2 + b * w + c
# 求导
[dy_dw] = tape.gradient(y, [w])
print(dy_dw)
'''


